#!/usr/bin/env python
# coding=utf-8
from google.appengine.ext.webapp import RequestHandler
from google.appengine.ext import db
import urllib
import hmac
import binascii
from model.model import Member
import os
from google.appengine.ext.webapp import template

PLAINTEXT = 'PLAINTEXT'
HMAC_SHA1 = 'HMAC-SHA1'

#对字符串进行编码,防止中间有特殊字符
def escape(s):
    """Escape a URL including any /."""
    return urllib.quote(s, safe='~')

def _utf8_str(s):
    """Convert unicode to utf-8."""
    if isinstance(s, unicode):
        return s.encode("utf-8")
    else:
        return str(s)

def generate_access_token(parameters):
    x_auth_username = parameters['x_auth_username']
    x_auth_password = parameters['x_auth_password']
    oauth_consumer_key = parameters['oauth_consumer_key'] 
#    oauth_token = parameters['oauth_token']
    oauth_signature_method = parameters['oauth_signature_method']
    oauth_signature = parameters['oauth_signature'] 
    oauth_timestamp = parameters['oauth_timestamp'] 
    oauth_nonce = parameters['oauth_nonce']
#    oauth_version = parameters['oauth_version']
#    oauth_verifier = parameters['oauth_verifier']
    result = x_auth_username + '|' + x_auth_password
    return result
    
def verify_access_token(access_token):
    parms = access_token.split('|')
    return parms[0],parms[1]

class BaseOauthRequest(RequestHandler):
    """OAuthRequest represents the request and can be serialized.

    OAuth parameters:
        - x_auth_username
        - x_auth_password
        - oauth_consumer_key 
        - oauth_token
        - oauth_signature_method
        - oauth_signature 
        - oauth_timestamp 
        - oauth_nonce
        - oauth_version
        - oauth_verifier
        ... any additional parameters, as defined by the Service Provider.
    """
    parameters = {}
    
    def get(self):
        self.readOauthHeader()
        
    def post(self):
        self.readOauthHeader()
    
    def readOauthHeader(self):
        self.parameters = {}
        if 'Authorization' in self.request.headers:
            auth_header = self.request.headers['Authorization']
            if auth_header[:6] == "OAuth ":
                auth_header = auth_header[6:]
            try:
                header_params = auth_header.split(',')
                for param in header_params:
                    param = param.strip()
                    if len(param)==0 or param.find('realm') > -1:
                        continue
                    params = param.split('=',1)
                    self.parameters[params[0]] = urllib.unquote(params[1].strip('\"'))
            except:
                raise OAuthError("Invalid Auth")
        else:
            raise OAuthError("Unauthorized")
    
    def get_normalized_parameters(self):
        """Return a string that contains the parameters that must be signed."""
        params = self.parameters
        try:
            # Exclude the signature if it exists.
            del params['oauth_signature']
        except:
            pass
        # Escape key values before sorting.
        key_values = [(escape(_utf8_str(k)), escape(_utf8_str(v))) \
            for k,v in params.items()]
        # Sort lexicographically, first after key, then after value.
        key_values.sort()
        # Combine key value pairs into a string.
        return '&'.join(['%s=%s' % (k, v) for k, v in key_values])
        
    def send_error(self,err_code,message):
        template_values = {}
        template_values['result'] = False
        template_values['message'] = message
        path = os.path.join(os.path.dirname(os.path.dirname(__file__)),'static','api','normalResult.json')
        self.response.headers['Content-type'] = "application/json"
        output = template.render(path,template_values)
        self.response.out.write(output)

class OAuthError(RuntimeError):
    """Generic exception class."""
    def __init__(self, message='OAuth error occured.'):
        self.message = message
        
class OAuthSignatureMethod(object):
    """A strategy class that implements a signature method."""
    def get_name(self):
        """-> str."""
        raise NotImplementedError

    def build_signature_base_string(self, oauth_request, oauth_consumer, oauth_token):
        """-> str key, str raw."""
        raise NotImplementedError

    def build_signature(self, oauth_request, oauth_consumer, oauth_token):
        """-> str."""
        raise NotImplementedError

    def check_signature(self, oauth_request, consumer, token, signature):
        built = self.build_signature(oauth_request, consumer, token)
        return built == signature        

class OAuthSignatureMethod_HMAC_SHA1(OAuthSignatureMethod):

    def get_name(self):
        return 'HMAC-SHA1'
        
    def build_signature_base_string(self, oauth_request, consumer, token):
        sig = (
            escape(oauth_request.request.method),
            escape(oauth_request.request.url),
            escape(oauth_request.get_normalized_parameters()),
        )

        key = '%s&' % escape(consumer.app_secret)
        if token:
            key += escape(token.access_token_secret)
        raw = '&'.join(sig)
        return key, raw

    def build_signature(self, oauth_request, consumer, token):
        """Builds the base signature string."""
        key, raw = self.build_signature_base_string(oauth_request, consumer,
            token)

        # HMAC object.
        try:
            import hashlib # 2.5
            hashed = hmac.new(key, raw, hashlib.sha1)
        except:
            import sha # Deprecated
            hashed = hmac.new(key, raw, sha)

        # Calculate the digest base 64.
        return binascii.b2a_base64(hashed.digest())[:-1]


class OAuthSignatureMethod_PLAINTEXT(OAuthSignatureMethod):

    def get_name(self):
        return 'PLAINTEXT'

    def build_signature_base_string(self, oauth_request, consumer, token):
        """Concatenates the consumer key and secret."""
        sig = '%s&' % escape(consumer.access_token_secret)
        if token:
            sig = sig + escape(token.access_token_secret)
        return sig, sig

    def build_signature(self, oauth_request, consumer, token):
        key, raw = self.build_signature_base_string(oauth_request, consumer,
            token)
        return key